using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Threading;

namespace System
{
	/// <summary>Represents a multicast delegate; that is, a delegate that can have more than one element in its invocation list.</summary>
	/// <filterpriority>2</filterpriority>
	[__DynamicallyInvokable]
	[ComVisible(true)]
	[Serializable]
	public abstract class MulticastDelegate : Delegate
	{
		[SecurityCritical]
		private object _invocationList;

		[SecurityCritical]
		private IntPtr _invocationCount;

		/// <summary>Initializes a new instance of the <see cref="T:System.MulticastDelegate" /> class.</summary>
		/// <param name="target">The object on which <paramref name="method" /> is defined. </param>
		/// <param name="method">The name of the method for which a delegate is created. </param>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
		protected MulticastDelegate(object target, string method) : base(target, method)
		{
		}

		/// <summary>Initializes a new instance of the <see cref="T:System.MulticastDelegate" /> class.</summary>
		/// <param name="target">The type of object on which <paramref name="method" /> is defined. </param>
		/// <param name="method">The name of the static method for which a delegate is created. </param>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
		protected MulticastDelegate(Type target, string method) : base(target, method)
		{
		}

		/// <summary>Combines this <see cref="T:System.Delegate" /> with the specified <see cref="T:System.Delegate" /> to form a new delegate.</summary>
		/// <returns>A delegate that is the new root of the <see cref="T:System.MulticastDelegate" /> invocation list.</returns>
		/// <param name="follow">The delegate to combine with this delegate. </param>
		/// <exception cref="T:System.ArgumentException">
		///   <paramref name="follow" /> does not have the same type as this instance.</exception>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		[SecuritySafeCritical]
		protected sealed override Delegate CombineImpl(Delegate follow)
		{
			object[] objArray;
			int num;
			if (follow == null)
			{
				return this;
			}
			if (!Delegate.InternalEqualTypes(this, follow))
			{
				throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
			}
			MulticastDelegate multicastDelegate = (MulticastDelegate)follow;
			int num1 = 1;
			object[] objArray1 = multicastDelegate._invocationList as object[];
			if (objArray1 != null)
			{
				num1 = (int)multicastDelegate._invocationCount;
			}
			object[] objArray2 = this._invocationList as object[];
			if (objArray2 == null)
			{
				num = 1 + num1;
				objArray = new object[num];
				objArray[0] = this;
				if (objArray1 != null)
				{
					for (int i = 0; i < num1; i++)
					{
						objArray[1 + i] = objArray1[i];
					}
				}
				else
				{
					objArray[1] = multicastDelegate;
				}
				return this.NewMulticastDelegate(objArray, num);
			}
			int num2 = (int)this._invocationCount;
			num = num2 + num1;
			objArray = null;
			if (num <= (int)objArray2.Length)
			{
				objArray = objArray2;
				if (objArray1 != null)
				{
					int num3 = 0;
					while (num3 < num1)
					{
						if (this.TrySetSlot(objArray, num2 + num3, objArray1[num3]))
						{
							num3++;
						}
						else
						{
							objArray = null;
							break;
						}
					}
				}
				else if (!this.TrySetSlot(objArray, num2, multicastDelegate))
				{
					objArray = null;
				}
			}
			if (objArray == null)
			{
				int length = (int)objArray2.Length;
				while (length < num)
				{
					length = length * 2;
				}
				objArray = new object[length];
				for (int j = 0; j < num2; j++)
				{
					objArray[j] = objArray2[j];
				}
				if (objArray1 != null)
				{
					for (int k = 0; k < num1; k++)
					{
						objArray[num2 + k] = objArray1[k];
					}
				}
				else
				{
					objArray[num2] = multicastDelegate;
				}
			}
			return this.NewMulticastDelegate(objArray, num, true);
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
		private void CtorClosed(object target, IntPtr methodPtr)
		{
			if (target == null)
			{
				this.ThrowNullThisInDelegateToInstance();
			}
			this._target = target;
			this._methodPtr = methodPtr;
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorClosedStatic(object target, IntPtr methodPtr)
		{
			this._target = target;
			this._methodPtr = methodPtr;
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorCollectibleClosedStatic(object target, IntPtr methodPtr, IntPtr gchandle)
		{
			this._target = target;
			this._methodPtr = methodPtr;
			this._methodBase = GCHandle.InternalGet(gchandle);
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorCollectibleOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle)
		{
			this._target = this;
			this._methodPtr = shuffleThunk;
			this._methodPtrAux = methodPtr;
			this._methodBase = GCHandle.InternalGet(gchandle);
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorCollectibleVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle)
		{
			this._target = this;
			this._methodPtr = shuffleThunk;
			this._methodPtrAux = base.GetCallStub(methodPtr);
			this._methodBase = GCHandle.InternalGet(gchandle);
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
		private void CtorOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk)
		{
			this._target = this;
			this._methodPtr = shuffleThunk;
			this._methodPtrAux = methodPtr;
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorRTClosed(object target, IntPtr methodPtr)
		{
			this._target = target;
			this._methodPtr = base.AdjustTarget(target, methodPtr);
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorSecureClosed(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
		{
			MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
			multicastDelegate.CtorClosed(target, methodPtr);
			this._invocationList = multicastDelegate;
			this._target = this;
			this._methodPtr = callThunk;
			this._methodPtrAux = creatorMethod;
			this._invocationCount = base.GetInvokeMethod();
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorSecureClosedStatic(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
		{
			MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
			multicastDelegate.CtorClosedStatic(target, methodPtr);
			this._invocationList = multicastDelegate;
			this._target = this;
			this._methodPtr = callThunk;
			this._methodPtrAux = creatorMethod;
			this._invocationCount = base.GetInvokeMethod();
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorSecureOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod)
		{
			MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
			multicastDelegate.CtorOpened(target, methodPtr, shuffleThunk);
			this._invocationList = multicastDelegate;
			this._target = this;
			this._methodPtr = callThunk;
			this._methodPtrAux = creatorMethod;
			this._invocationCount = base.GetInvokeMethod();
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorSecureRTClosed(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
		{
			MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
			multicastDelegate.CtorRTClosed(target, methodPtr);
			this._invocationList = multicastDelegate;
			this._target = this;
			this._methodPtr = callThunk;
			this._methodPtrAux = creatorMethod;
			this._invocationCount = base.GetInvokeMethod();
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorSecureVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod)
		{
			MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
			multicastDelegate.CtorVirtualDispatch(target, methodPtr, shuffleThunk);
			this._invocationList = multicastDelegate;
			this._target = this;
			this._methodPtr = callThunk;
			this._methodPtrAux = creatorMethod;
			this._invocationCount = base.GetInvokeMethod();
		}

		[DebuggerNonUserCode]
		[ForceTokenStabilization]
		[SecurityCritical]
		private void CtorVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk)
		{
			this._target = this;
			this._methodPtr = shuffleThunk;
			this._methodPtrAux = base.GetCallStub(methodPtr);
		}

		[SecurityCritical]
		private object[] DeleteFromInvocationList(object[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
		{
			int length = (int)(this._invocationList as object[]).Length;
			while (length / 2 >= invocationCount - deleteCount)
			{
				length = length / 2;
			}
			object[] objArray = new object[length];
			for (int i = 0; i < deleteIndex; i++)
			{
				objArray[i] = invocationList[i];
			}
			for (int j = deleteIndex + deleteCount; j < invocationCount; j++)
			{
				objArray[j - deleteCount] = invocationList[j];
			}
			return objArray;
		}

		private bool EqualInvocationLists(object[] a, object[] b, int start, int count)
		{
			for (int i = 0; i < count; i++)
			{
				if (!a[start + i].Equals(b[i]))
				{
					return false;
				}
			}
			return true;
		}

		/// <summary>Determines whether this multicast delegate and the specified object are equal.</summary>
		/// <returns>true if <paramref name="obj" /> and this instance have the same invocation lists; otherwise, false.</returns>
		/// <param name="obj">The object to compare with this instance. </param>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		/// <filterpriority>2</filterpriority>
		[__DynamicallyInvokable]
		[SecuritySafeCritical]
		public sealed override bool Equals(object obj)
		{
			if (obj == null || !Delegate.InternalEqualTypes(this, obj))
			{
				return false;
			}
			MulticastDelegate multicastDelegate = obj as MulticastDelegate;
			if (multicastDelegate == null)
			{
				return false;
			}
			if (this._invocationCount == (IntPtr)0)
			{
				if (!this.InvocationListLogicallyNull())
				{
					if (!this._invocationList.Equals(multicastDelegate._invocationList))
					{
						return false;
					}
					return base.Equals(multicastDelegate);
				}
				if (!(multicastDelegate._invocationList is Delegate))
				{
					return base.Equals(multicastDelegate);
				}
				return this.Equals(multicastDelegate._invocationList);
			}
			if (!this.InvocationListLogicallyNull())
			{
				if (!(this._invocationList is Delegate))
				{
					return this.InvocationListEquals(multicastDelegate);
				}
				return this._invocationList.Equals(obj);
			}
			if (this.IsUnmanagedFunctionPtr())
			{
				if (!multicastDelegate.IsUnmanagedFunctionPtr())
				{
					return false;
				}
				return Delegate.CompareUnmanagedFunctionPtrs(this, multicastDelegate);
			}
			if (!(multicastDelegate._invocationList is Delegate))
			{
				return base.Equals(obj);
			}
			return this.Equals(multicastDelegate._invocationList);
		}

		/// <summary>Returns the hash code for this instance.</summary>
		/// <returns>A 32-bit signed integer hash code.</returns>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		/// <filterpriority>2</filterpriority>
		[__DynamicallyInvokable]
		[SecuritySafeCritical]
		public sealed override int GetHashCode()
		{
			if (this.IsUnmanagedFunctionPtr())
			{
				return ValueType.GetHashCodeOfPtr(this._methodPtr) ^ ValueType.GetHashCodeOfPtr(this._methodPtrAux);
			}
			object[] objArray = this._invocationList as object[];
			if (objArray == null)
			{
				return base.GetHashCode();
			}
			int hashCode = 0;
			for (int i = 0; i < (int)this._invocationCount; i++)
			{
				hashCode = hashCode * 33 + objArray[i].GetHashCode();
			}
			return hashCode;
		}

		/// <summary>Returns the invocation list of this multicast delegate, in invocation order.</summary>
		/// <returns>An array of delegates whose invocation lists collectively match the invocation list of this instance.</returns>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		/// <filterpriority>2</filterpriority>
		[__DynamicallyInvokable]
		[SecuritySafeCritical]
		public sealed override Delegate[] GetInvocationList()
		{
			Delegate[] delegateArray;
			object[] objArray = this._invocationList as object[];
			if (objArray != null)
			{
				int num = (int)this._invocationCount;
				delegateArray = new Delegate[num];
				for (int i = 0; i < num; i++)
				{
					delegateArray[i] = (Delegate)objArray[i];
				}
			}
			else
			{
				delegateArray = new Delegate[] { this };
			}
			return delegateArray;
		}

		/// <summary>Returns a static method represented by the current <see cref="T:System.MulticastDelegate" />.</summary>
		/// <returns>A static method represented by the current <see cref="T:System.MulticastDelegate" />.</returns>
		[SecuritySafeCritical]
		protected override MethodInfo GetMethodImpl()
		{
			if (this._invocationCount != (IntPtr)0 && this._invocationList != null)
			{
				object[] objArray = this._invocationList as object[];
				if (objArray != null)
				{
					int num = (int)this._invocationCount - 1;
					return ((Delegate)objArray[num]).Method;
				}
				MulticastDelegate multicastDelegate = this._invocationList as MulticastDelegate;
				if (multicastDelegate != null)
				{
					return multicastDelegate.GetMethodImpl();
				}
			}
			else if (this.IsUnmanagedFunctionPtr())
			{
				if (this._methodBase == null || !(this._methodBase is MethodInfo))
				{
					IRuntimeMethodInfo runtimeMethodInfo = base.FindMethodHandle();
					RuntimeType declaringType = RuntimeMethodHandle.GetDeclaringType(runtimeMethodInfo);
					if (RuntimeTypeHandle.IsGenericTypeDefinition(declaringType) || RuntimeTypeHandle.HasInstantiation(declaringType))
					{
						declaringType = base.GetType() as RuntimeType;
					}
					this._methodBase = (MethodInfo)RuntimeType.GetMethodBase(declaringType, runtimeMethodInfo);
				}
				return (MethodInfo)this._methodBase;
			}
			return base.GetMethodImpl();
		}

		/// <summary>Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo" /> object with all the data needed to serialize this instance.</summary>
		/// <param name="info">An object that holds all the data needed to serialize or deserialize this instance. </param>
		/// <param name="context">(Reserved) The location where serialized data is stored and retrieved. </param>
		/// <exception cref="T:System.ArgumentNullException">
		///   <paramref name="info" /> is null. </exception>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		/// <exception cref="T:System.Runtime.Serialization.SerializationException">A serialization error occurred.</exception>
		/// <filterpriority>2</filterpriority>
		/// <PermissionSet>
		///   <IPermission class="System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="MemberAccess" />
		/// </PermissionSet>
		[SecurityCritical]
		public override void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			int num = 0;
			object[] objArray = this._invocationList as object[];
			if (objArray == null)
			{
				MethodInfo method = base.Method;
				if (!(method is RuntimeMethodInfo) || this.IsUnmanagedFunctionPtr())
				{
					throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
				}
				if (!this.InvocationListLogicallyNull() && !this._invocationCount.IsNull() && !this._methodPtrAux.IsNull())
				{
					throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
				}
				DelegateSerializationHolder.GetDelegateSerializationInfo(info, base.GetType(), base.Target, method, num);
				return;
			}
			DelegateSerializationHolder.DelegateEntry delegateEntry = null;
			int num1 = (int)this._invocationCount;
			while (true)
			{
				int num2 = num1 - 1;
				num1 = num2;
				if (num2 < 0)
				{
					break;
				}
				MulticastDelegate multicastDelegate = (MulticastDelegate)objArray[num1];
				MethodInfo methodInfo = multicastDelegate.Method;
				if (methodInfo is RuntimeMethodInfo && !this.IsUnmanagedFunctionPtr() && (multicastDelegate.InvocationListLogicallyNull() || multicastDelegate._invocationCount.IsNull() || multicastDelegate._methodPtrAux.IsNull()))
				{
					int num3 = num;
					num = num3 + 1;
					DelegateSerializationHolder.DelegateEntry delegateSerializationInfo = DelegateSerializationHolder.GetDelegateSerializationInfo(info, multicastDelegate.GetType(), multicastDelegate.Target, methodInfo, num3);
					if (delegateEntry != null)
					{
						delegateEntry.Entry = delegateSerializationInfo;
					}
					delegateEntry = delegateSerializationInfo;
				}
			}
			if (delegateEntry == null)
			{
				throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
			}
		}

		[SecuritySafeCritical]
		internal override object GetTarget()
		{
			if (this._invocationCount != (IntPtr)0)
			{
				if (this.InvocationListLogicallyNull())
				{
					return null;
				}
				object[] objArray = this._invocationList as object[];
				if (objArray != null)
				{
					int num = (int)this._invocationCount;
					return ((Delegate)objArray[num - 1]).GetTarget();
				}
				Delegate @delegate = this._invocationList as Delegate;
				if (@delegate != null)
				{
					return @delegate.GetTarget();
				}
			}
			return base.GetTarget();
		}

		[SecuritySafeCritical]
		private bool InvocationListEquals(MulticastDelegate d)
		{
			object[] objArray = this._invocationList as object[];
			if (d._invocationCount != this._invocationCount)
			{
				return false;
			}
			int num = (int)this._invocationCount;
			for (int i = 0; i < num; i++)
			{
				if (!((Delegate)objArray[i]).Equals((d._invocationList as object[])[i]))
				{
					return false;
				}
			}
			return true;
		}

		[SecuritySafeCritical]
		internal bool InvocationListLogicallyNull()
		{
			if (this._invocationList == null || this._invocationList is LoaderAllocator)
			{
				return true;
			}
			return this._invocationList is DynamicResolver;
		}

		[SecuritySafeCritical]
		internal bool IsUnmanagedFunctionPtr()
		{
			return this._invocationCount == (IntPtr)-1;
		}

		[SecurityCritical]
		private MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount, bool thisIsMultiCastAlready)
		{
			MulticastDelegate multicastInvoke = Delegate.InternalAllocLike(this);
			if (!thisIsMultiCastAlready)
			{
				multicastInvoke._methodPtr = base.GetMulticastInvoke();
				multicastInvoke._methodPtrAux = base.GetInvokeMethod();
			}
			else
			{
				multicastInvoke._methodPtr = this._methodPtr;
				multicastInvoke._methodPtrAux = this._methodPtrAux;
			}
			multicastInvoke._target = multicastInvoke;
			multicastInvoke._invocationList = invocationList;
			multicastInvoke._invocationCount = (IntPtr)invocationCount;
			return multicastInvoke;
		}

		[SecurityCritical]
		[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
		internal MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount)
		{
			return this.NewMulticastDelegate(invocationList, invocationCount, false);
		}

		/// <summary>Determines whether two <see cref="T:System.MulticastDelegate" /> objects are equal.</summary>
		/// <returns>true if <paramref name="d1" /> and <paramref name="d2" /> have the same invocation lists; otherwise, false.</returns>
		/// <param name="d1">The left operand. </param>
		/// <param name="d2">The right operand. </param>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		/// <filterpriority>3</filterpriority>
		[__DynamicallyInvokable]
		public static bool operator ==(MulticastDelegate d1, MulticastDelegate d2)
		{
			if (d1 == null)
			{
				return d2 == null;
			}
			return d1.Equals(d2);
		}

		/// <summary>Determines whether two <see cref="T:System.MulticastDelegate" /> objects are not equal.</summary>
		/// <returns>true if <paramref name="d1" /> and <paramref name="d2" /> do not have the same invocation lists; otherwise, false.</returns>
		/// <param name="d1">The left operand. </param>
		/// <param name="d2">The right operand. </param>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		/// <filterpriority>3</filterpriority>
		[__DynamicallyInvokable]
		public static bool operator !=(MulticastDelegate d1, MulticastDelegate d2)
		{
			if (d1 == null)
			{
				return d2 != null;
			}
			return !d1.Equals(d2);
		}

		/// <summary>Removes an element from the invocation list of this <see cref="T:System.MulticastDelegate" /> that is equal to the specified delegate.</summary>
		/// <returns>If <paramref name="value" /> is found in the invocation list for this instance, then a new <see cref="T:System.Delegate" /> without <paramref name="value" /> in its invocation list; otherwise, this instance with its original invocation list.</returns>
		/// <param name="value">The delegate to search for in the invocation list. </param>
		/// <exception cref="T:System.MemberAccessException">Cannot create an instance of an abstract class, or this member was invoked with a late-binding mechanism. </exception>
		[SecuritySafeCritical]
		protected sealed override Delegate RemoveImpl(Delegate value)
		{
			MulticastDelegate multicastDelegate = value as MulticastDelegate;
			if (multicastDelegate == null)
			{
				return this;
			}
			if (multicastDelegate._invocationList is object[])
			{
				object[] objArray = this._invocationList as object[];
				if (objArray != null)
				{
					int num = (int)this._invocationCount;
					int num1 = (int)multicastDelegate._invocationCount;
					for (int i = num - num1; i >= 0; i--)
					{
						if (this.EqualInvocationLists(objArray, multicastDelegate._invocationList as object[], i, num1))
						{
							if (num - num1 == 0)
							{
								return null;
							}
							if (num - num1 == 1)
							{
								return (Delegate)objArray[(i != 0 ? 0 : num - 1)];
							}
							object[] objArray1 = this.DeleteFromInvocationList(objArray, num, i, num1);
							return this.NewMulticastDelegate(objArray1, num - num1, true);
						}
					}
				}
			}
			else
			{
				object[] objArray2 = this._invocationList as object[];
				if (objArray2 != null)
				{
					int num2 = (int)this._invocationCount;
					int num3 = num2;
					do
					{
						int num4 = num3 - 1;
						num3 = num4;
						if (num4 >= 0)
						{
							continue;
						}
						return this;
					}
					while (!value.Equals(objArray2[num3]));
					if (num2 == 2)
					{
						return (Delegate)objArray2[1 - num3];
					}
					object[] objArray3 = this.DeleteFromInvocationList(objArray2, num2, num3, 1);
					return this.NewMulticastDelegate(objArray3, num2 - 1, true);
				}
				else if (this.Equals(value))
				{
					return null;
				}
			}
			return this;
		}

		[SecurityCritical]
		internal void StoreDynamicMethod(MethodInfo dynamicMethod)
		{
			if (this._invocationCount == (IntPtr)0)
			{
				this._methodBase = dynamicMethod;
				return;
			}
			((MulticastDelegate)this._invocationList)._methodBase = dynamicMethod;
		}

		[DebuggerNonUserCode]
		private void ThrowNullThisInDelegateToInstance()
		{
			throw new ArgumentException(Environment.GetResourceString("Arg_DlgtNullInst"));
		}

		[SecurityCritical]
		private bool TrySetSlot(object[] a, int index, object o)
		{
			if (a[index] == null && Interlocked.CompareExchange<object>(ref a[index], o, null) == null)
			{
				return true;
			}
			if (a[index] != null)
			{
				MulticastDelegate multicastDelegate = (MulticastDelegate)o;
				MulticastDelegate multicastDelegate1 = (MulticastDelegate)a[index];
				if (multicastDelegate1._methodPtr == multicastDelegate._methodPtr && multicastDelegate1._target == multicastDelegate._target && multicastDelegate1._methodPtrAux == multicastDelegate._methodPtrAux)
				{
					return true;
				}
			}
			return false;
		}
	}
}